Dynamic Workers โ€” Walkthrough Cheat Sheet

Talk track for demoing Cloudflare Dynamic Workers with Egress Control on a customer call. 10 to 15 minutes. Natural language. Three scenarios, escalating from "no network" to "real production pattern."

The arc at a glance

01When to bring this up (qualifying questions)2 min 02The 30-second product pitch1 min 03Scenario A: Block all egress2 min 04Scenario B: Allow-list one domain3 min 05Scenario C: Inject credentials3 min 06The architectural punchline1 min 07Close + back-pocket Q&A2 min
๐ŸŽฌ
Open this in a fresh tab before the call
cf-demo-app.dustinburke23nc.workers.dev/dynamic-workers-demo
3 toggleable scenarios. Editor on the left, output + gateway log on the right.

01 When to bring this up ~2 min

Dynamic Workers isn't a "lead with this" product. It's the right answer when the customer has a specific problem. Listen for these triggers in conversation.

Listen for:
"We're building an AI agent that needs to execute code."
"Our platform lets customers upload scripts or run their own logic."
"We use Replit / E2B / Daytona / containers to sandbox user code."
"How do we run untrusted code safely?"
"We need to sandbox LLM-generated code."
"Our agent calls external APIs and we don't want the model to see the secrets."

If you hear any of those, that's when Dynamic Workers + Egress Control is the right play.

This is a developer-platform product. If the customer is a CIO or finance buyer talking about VPN or ZTNA, this is NOT the right product to lead with. Save it for the technical conversation, or for platform-builder customers (SaaS companies, AI agent companies, developer tools companies).

02 The 30-second product pitch ~1 min

"Cloudflare just launched something called Dynamic Workers. The simple version is, it lets you spin up an isolated Worker at runtime to execute code you don't trust. Think AI agent writing and running code, or customer-supplied scripts on your platform. The killer feature is egress control. You decide exactly what the spun-up Worker can talk to on the internet. Want to show you three patterns?"

If they nod, switch to the demo page and pick Scenario A.


03 Scenario A ยท Block all egress ~2 min

๐Ÿšซ Scenario A โ€” Block all egress

The strictest mode. Spun-up Worker can do compute, but cannot reach the network at all. Any fetch throws.

Click Scenario A on the page (red border).

"First pattern, the simplest. The Worker code on the left tries to call fetch("https://example.com"). Watch what happens when I hit Run."

Click โ–ถ Run in Dynamic Worker.

"Look at the output. The fetch threw immediately. The Worker never reached the network. Look at the gateway log on the right โ€” one entry, action BLOCKED. globalOutbound: null is the magic line in the parent Worker that does this. The child code is completely isolated from the internet."

โšก The point to land

"This is the maximum-isolation mode. If you're running code that should never call out, this gives you a guarantee, not just a policy hope. The runtime physically can't make the call."

"That's the strict version. But most real use cases need some network access. Let me show you the next pattern."

04 Scenario B ยท Allow-list one domain ~3 min

๐Ÿ›‚ Scenario B โ€” Allow-list one domain

Real production pattern. Spun-up Worker can reach approved destinations, blocked from everything else. Gateway in the middle decides per-request.

Click Scenario B (yellow border).

"Same setup, but this time the parent Worker passes a gateway in instead of just null. The gateway is a class you write โ€” it sees every fetch the child makes and decides what to do with it. In this example, the gateway only allows requests to api.github.com. Everything else is blocked."

Show the code in the editor โ€” point at the two fetches (github + example.com).

"This child code tries two URLs. One to github, one to example.com. Watch what comes back."

Click โ–ถ Run in Dynamic Worker.

"Two log entries. Github โ€” ALLOWED, forwarded to upstream. Example.com โ€” BLOCKED, gateway returned 403. The child Worker had no idea which one would succeed. It just called fetch like a normal Worker would. The gateway decided."

โšก The point to land

"This is how you give an AI agent or a customer script controlled internet access. You define an allow-list at the gateway. The child code calls fetch normally. The gateway is the bouncer."

Good moment to ask: "Where in your product would this fit? Is there a piece of your stack today where you'd want to give code controlled, narrow internet access?"
"And here's where it gets interesting for security. The gateway can do more than block โ€” it can also modify."

05 Scenario C ยท Inject credentials ~3 min

๐Ÿ”‘ Scenario C โ€” Inject credentials

The "wow" pattern. Child Worker calls an API with no auth header. Gateway intercepts and injects the Bearer token before forwarding. Child code never sees the secret.

Click Scenario C (green border).

"Look at the child code. It calls fetch("https://api.example-demo.dev/whoami"). No Authorization header. No token. Nothing. Now watch what comes back."

Click โ–ถ Run in Dynamic Worker.

"Two things to point out. First, look at the response body. The upstream API responded as if the request was authenticated. authenticated: true, tenant ID, a token preview. Second, look at the gateway log โ€” it says INJECTED with the Bearer token that was added. The child code never had access to that token. It just called fetch. The gateway added the auth header on the way out."

โšก The point to land

"This is huge for AI agent use cases. The agent code can call your APIs without ever seeing the API keys. You inject credentials at the gateway, scoped per tenant if you want. The model can't leak what it doesn't know."

"Same pattern works for any per-tenant context. The gateway has ctx.props โ€” you can pass tenant ID, customer ID, scoped permissions, anything. Each spun-up Worker gets its own gateway stub with its own props. One class, infinite scoping."
Good moment to ask: "Do you have a place in your platform today where you're worried about secrets being exposed to user code or AI-generated code?"

06 The architectural punchline ~1 min

"Step back for a second. What you just saw is three flavors of the same primitive. Block all, filter selectively, transparently augment. The child Worker code is the same in all three cases. What changes is the parent Worker's configuration. That separation matters because it means your platform team controls the security posture, and the AI agent (or customer script, or whatever) just writes code. They don't have to know about the gateway. They don't have to handle credentials. They don't have to know which destinations are allowed. That's the whole point of capability-based sandboxing."

โšก Optional follow-on if they're technical

If they're curious about how it works under the hood, mention Cap'n Web โ€” Cloudflare's RPC system that powers this. Stubs can't be forged. Child Workers can only access what they receive. Same security model Android (Binder) and Chrome (Mojo) use, but exposed directly to you as the developer.


07 Close + back-pocket Q&A ~2 min

"Two things from here. First, the playground we just ran is open source โ€” it's at github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground. You can deploy your own copy in about five minutes if you want to play with it on your account. Second, this is generally available on the Workers Paid plan. If you're already running Workers in production, it's just turning on a new binding."

Back-pocket Q&A

"How is this different from containers?"

"Containers are heavy. They have cold-start times measured in seconds, you have to manage images, networking, lifecycle. Dynamic Workers spin up in milliseconds at the edge, in 330+ cities. Use containers when you need a full OS. Use Dynamic Workers when you need to run code."

"What can the spun-up Worker actually do?"

"Anything a regular Worker can do. Compute, KV, R2, D1, Vectorize, Workers AI, the whole platform. The parent decides which bindings the child receives. Default-deny, then explicitly hand it the capabilities it needs."

"What about limits? Can a runaway script burn through CPU?"

"You can set custom limits on the child Worker. CPU time, memory, request count. The parent enforces them. Plus you get full observability โ€” attach a Tail Worker, capture logs, audit every run."

"Is the gateway pattern the same as a service binding?"

"Same underlying mechanism โ€” WorkerEntrypoint with RPC. The difference is the gateway gets ctx.props for per-request context, and it specifically intercepts globalOutbound. Think of it as a service binding with a specific job."

"Can I run untrusted code from the public internet directly?"

"That's the use case. Customer uploads a script, AI agent generates code, someone pastes code in a playground UI. You load it into a Dynamic Worker with your sandbox config, run it, return the result. Capability-based sandboxing. The code can only do what you let it do."

08 Pre-call checklist do 2 min before

This demo runs on a worker.dev simulation (paid Workers required for the real product). The simulation looks identical and behaves exactly the same way, but the page is honest about it.

  1. Open cf-demo-app.dustinburke23nc.workers.dev/dynamic-workers-demo in a fresh tab.
  2. Click Scenario A so the page is on the first tab when you share screen.
  3. Have this cheat sheet open in a second window (don't share it).
  4. If you want to deploy the real thing on your account later, the playground at github.com/cloudflare/agents/tree/main/examples/dynamic-workers-playground takes about 5 minutes to deploy.

โšก Honest disclosure during the demo

If a customer asks "is this hitting a real Dynamic Worker right now?" the answer is no โ€” it's a faithful simulation because the lab account is on the free Workers plan, and Dynamic Workers requires Workers Paid. The page makes this explicit at the top. Don't try to hide it. The simulation behaves identically to what a real Dynamic Worker would do, which is the point.